home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / Pascal / Snippets / Event speed / Event speed.p < prev    next >
Text File  |  1997-01-21  |  7KB  |  237 lines

  1. {Event processing speed test}
  2. {By Ingemar Ragnemalm 1997}
  3.  
  4. {Many game programmers claim that you should not process events at all, not even with GetOSEvent,}
  5. {because it is too slow. Others claim that you should always use WaitNextEvent no matter what.}
  6. {}
  7. {I say that both are wrong. GetOSEvent is very fast. WaitNextEvent is not, not even when quitting all}
  8. {other applications except Finder, and quitting the Finder is no good habit IMHO. Reading the keyboard}
  9. {with GetKeys is fast, but hopelessly incompatible with other keyboard layouts than your own. There}
  10. {is a workaround, but few use it.}
  11. {}
  12. {This application is an experiment, to find out the truth. You can select any of four methods,}
  13. {GetNextEvent, WaitNextEvent( with a sleep time of zero), GetOSEvent and None (which uses Button}
  14. {and GetKeys).}
  15. {}
  16. {In my experiments, GetOSEvent had no significant disadvantage to Button/GetKeys. It even was}
  17. {a fair bit faster in many tests! Feel free to draw conclusions, and to hunt down any mistakes I may}
  18. {have made. This was a quick hack, and sure I may have overlooked something – but I kind of doubt it.}
  19.  
  20. program EventSpeed;
  21.     uses
  22. {$ifc UNDEFINED THINK_PASCAL}
  23.         Types, QuickDraw, Events, Windows, Dialogs, Fonts, DiskInit, TextEdit, Traps,{}
  24.         Memory, SegLoad, Scrap, ToolUtils, OSUtils, Menus, Resources, StandardFile,{}
  25.         GestaltEqu, Files, Errors, Devices, QuickDrawText, 
  26. {$elsec}
  27.         InterfacesUI, 
  28. {$endc}
  29.         MyFakeAlert;
  30.  
  31.     var
  32.         myEvent: EventRecord;
  33.         w, whichWindow: WindowPtr;
  34.         appleMenu, fileMenu: MenuHandle;
  35.         gDone: Boolean;
  36.  
  37.         eventMode: Integer;
  38.  
  39.     const
  40.         useGNE = 1;
  41.         useWNE = 2;
  42.         useGOE = 3;
  43.         useNone = 4;
  44.  
  45.     procedure SynchMenus;
  46.     begin
  47.         CheckItem(fileMenu, useGNE, eventMode = useGNE);
  48.         CheckItem(fileMenu, useWNE, eventMode = useWNE);
  49.         CheckItem(fileMenu, useGOE, eventMode = useGOE);
  50.         CheckItem(fileMenu, useNone, eventMode = useNone);
  51.     end; {SynchMenus}
  52.  
  53.     procedure SetupMenus;
  54.     begin
  55.         appleMenu := NewMenu(128, stringof(char($14)));
  56.         AppendMenu(appleMenu, 'About Event processing speed test…;(-');
  57.         AppendResMenu(appleMenu, 'DRVR');
  58.         InsertMenu(appleMenu, 0);            { put apple menu at end of menu bar }
  59.  
  60.         fileMenu := NewMenu(129, 'File');
  61.         AppendMenu(fileMenu, 'GetNextEvent/G;WaitNextEvent/W;GetOSEvent/O;None/N;(-;Quit/Q');
  62.         InsertMenu(fileMenu, 0);            { put file menu at end of menu bar }
  63.         DrawMenuBar;
  64.         SynchMenus;
  65.     end; {SetupMenus}
  66.  
  67.     procedure MenuSelection (theSelection: Longint);
  68.         var
  69.             name: Str255;
  70.             saveport: GrafPtr;
  71.     begin
  72.         case HiWord(theSelection) of
  73.             128: 
  74.                 begin
  75.                     if LoWord(theSelection) = 1 then
  76.                         ReportStr('Experimental program. Why are game programmers so scared of GetOSEvent?')
  77.                     else
  78.                         begin
  79.                             GetPort(saveport);
  80.                             GetMenuItemText(appleMenu, 1, name);    (* get name *)
  81.                             if OpenDeskAcc(name) = 0 then (* run the desk accessory *)
  82.                                 ;
  83.                             SetPort(saveport);
  84.                         end;
  85.                 end;
  86.             129: 
  87.                 case LoWord(theSelection) of
  88.                     useGNE, useWNE, useGOE, useNone: 
  89.                         eventMode := LoWord(theSelection);
  90.                     otherwise
  91.                         gDone := true;
  92.                 end; {case MenuSelect}
  93.             otherwise
  94.         end;
  95.         SynchMenus;
  96.         HiLiteMenu(0);
  97.     end; {MenuSelection}
  98.  
  99.     procedure HandleEvents;
  100.         var
  101.             hasEvent: Boolean;
  102.             theKey: Char;
  103.             whichPart: Integer;
  104.             theSelection: Longint;
  105.             myKeyMap: KeyMap;
  106.     begin
  107.         case eventMode of
  108.             useGNE: 
  109.                 begin
  110. {GetNextEvent is the old event processing method.}
  111.                     SystemTask;
  112.                     hasEvent := GetNextEvent(everyEvent, myEvent);
  113.                 end;
  114.             useWNE:
  115. {WaitNextEvent is the new event processing method, recommended by Apple.}
  116. {The wait time is set to zero to get maximum performance (which also means that it is very unfriendly to}
  117. {other processes). It should NOT use zero if switched to the background - if it processes background events}
  118. {at all!}
  119.                 hasEvent := WaitNextEvent(everyEvent, myEvent, 0, nil);
  120.             useGOE:
  121. {GetOSEvent is an low-level event processing method that doesn't give time to other processes at all.}
  122. {It is therefore very fast, but many newbie game programmers don't dare using it anyway. I think they should.}
  123.                 hasEvent := GetOSEvent(everyEvent, myEvent);        {or perhaps mDownMask + updateMask + keyDownMask}
  124.             useNone: 
  125.                 begin
  126.                     hasEvent := false;
  127. {When Button is down, get an event the usual way. This means that menus are suppirted, but command-key}
  128. {equivalents are not. Button and GetKeys is what many games use.}
  129.                     if Button then
  130.                         hasEvent := WaitNextEvent(everyEvent, myEvent, 0, nil)
  131.                     else
  132.                         begin
  133.                             GetKeys(myKeyMap);
  134.                             if myKeyMap[12] and myKeyMap[55] then
  135.                                 gDone := true; {Command-Q?}
  136. {Here we could find if command-Q is pressed etc. Rather tedious compared to doing it with events, and}
  137. {you can't be sure that all keyboards follow your layout! (Most special keys don't, like "+" and "-".)}
  138. {If you must use GetKeys, you should use KeyTrans/KeyTranslate.}
  139.                         end;
  140.                 end;
  141.             otherwise
  142.                 begin
  143.                     SysBeep(1);
  144.                     hasEvent := WaitNextEvent(everyEvent, myEvent, 0, nil);
  145.                 end;
  146.         end; {case}
  147.  
  148.         if hasEvent then
  149.             case myEvent.what of
  150.                 updateEvt: 
  151.                     if WindowPtr(myEvent.message) = w then
  152.                         begin
  153.                             BeginUpdate(w);
  154. {Draw here!}
  155.                             PaintRect(w^.portRect);
  156.                             EndUpdate(w);
  157.                         end;
  158.                 keyDown: 
  159.                     begin
  160.                         theKey := char(BitAnd(myEvent.message, charCodeMask));
  161.                         if (BitAnd(myEvent.modifiers, cmdKey) <> 0) then
  162.                             MenuSelection(MenuKey(theKey))
  163.                         else
  164. {DoKey(theKey, theEvent.modifiers)}
  165.                             ;
  166.                     end;
  167.                 mouseDown: 
  168.                     begin
  169.                         whichPart := FindWindow(myEvent.where, whichWindow);
  170.                         case whichPart of
  171.                             inMenuBar: 
  172.                                 begin
  173.                                     theSelection := MenuSelect(myEvent.where);
  174.                                     MenuSelection(theSelection);
  175.                                 end;
  176.                             inSysWindow: 
  177.                                 SystemClick(myEvent, whichWindow);
  178.                             inContent: 
  179.                                 begin
  180.                                 end;
  181.                             otherwise
  182.                         end; {case whichPart}
  183.                     end;
  184.  
  185.                 otherwise
  186.             end;{case myEvent.what}
  187.     end; {HandleEvents}
  188.  
  189.     var
  190.         i, j: Integer;
  191.         pat: PixPatHandle;
  192.         numLoops: Longint;
  193.         startTicks: Longint;
  194.         drawRect: Rect;
  195.  
  196. begin
  197. {CodeWarrior needs inits here}
  198. {$IFC UNDEFINED THINK_PASCAL}
  199.     { Initialize all the needed managers. }
  200.     InitGraf(@qd.thePort);
  201.     InitFonts;
  202.     InitWindows;
  203.     InitMenus;
  204.     TEInit;
  205.     InitDialogs(nil);
  206.     MaxApplZone;
  207. {$ENDC}
  208.  
  209.     w := GetNewCWindow(128, nil, WindowPtr(-1));
  210.     pat := GetPixPat(128);
  211.     SetPort(w);
  212.     PenPixPat(pat);
  213.  
  214.     eventMode := useGNE;
  215.     SetupMenus;
  216.  
  217.     InitCursor;
  218.  
  219.     numLoops := 0;
  220.     SetRect(drawRect, 0, 0, 150, 30);
  221.     startTicks := TickCount;
  222.     repeat
  223.         HandleEvents;
  224.         numLoops := numLoops + 1;
  225.  
  226. {After 60 ticks have passed, print out the number of loops!}
  227.         if startTicks + 60 <= TickCount then
  228.             begin
  229.                 EraseRect(drawRect);
  230.                 MoveTo(4, 20);
  231.                 DrawString(StringOf(numLoops : 1, ' loops/sec'));
  232.                 startTicks := TickCount;
  233.                 numLoops := 0;
  234.             end;
  235.  
  236.     until gDone;
  237. end.